x86: Fix event-channel access for 32-bit HVM guests.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 3 Mar 2009 13:17:05 +0000 (13:17 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 3 Mar 2009 13:17:05 +0000 (13:17 +0000)
Based on a patch by Joe Jin <joe.jin@oracle.com>

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
12 files changed:
xen/arch/x86/domain.c
xen/arch/x86/domctl.c
xen/arch/x86/irq.c
xen/arch/x86/traps.c
xen/common/domctl.c
xen/common/event_channel.c
xen/common/keyhandler.c
xen/common/trace.c
xen/common/xenoprof.c
xen/include/asm-x86/domain.h
xen/include/xen/compat.h
xen/include/xen/sched.h

index 4d5cc9d75b7ee9a17f7482345bf0a5f9d9853e4c..84d08dd97de3a712e8e40795320bb8d4ee733ca0 100644 (file)
@@ -840,7 +840,7 @@ map_vcpu_info(struct vcpu *v, unsigned long mfn, unsigned offset)
      * lost.  The domain will get a spurious event, but it can cope.
      */
     vcpu_info(v, evtchn_upcall_pending) = 1;
-    for ( i = 0; i < BITS_PER_GUEST_LONG(d); i++ )
+    for ( i = 0; i < BITS_PER_EVTCHN_WORD(d); i++ )
         set_bit(i, &vcpu_info(v, evtchn_pending_sel));
 
     return 0;
index ab28b22725cd39d6c13866aa7a74c12b69e4acf6..e17197c19b759676f28d9c61257f23844f939dc4 100644 (file)
@@ -494,7 +494,8 @@ long arch_do_domctl(
             break;
         }
 
-        domctl->u.address_size.size = BITS_PER_GUEST_LONG(d);
+        domctl->u.address_size.size =
+            is_pv_32on64_domain(d) ? 32 : BITS_PER_LONG;
 
         ret = 0;
         rcu_unlock_domain(d);
index a0829a05bac0ec217c7d19b07f502f1029ac2f22..18baba02dbec6888c292930f35b8841097d15a66 100644 (file)
@@ -1104,7 +1104,8 @@ static void dump_irqs(unsigned char key)
                        (test_bit(d->pirq_to_evtchn[irq],
                                  &shared_info(d, evtchn_pending)) ?
                         'P' : '-'),
-                       (test_bit(d->pirq_to_evtchn[irq]/BITS_PER_GUEST_LONG(d),
+                       (test_bit(d->pirq_to_evtchn[irq] /
+                                 BITS_PER_EVTCHN_WORD(d),
                                  &vcpu_info(d->vcpu[0], evtchn_pending_sel)) ?
                         'S' : '-'),
                        (test_bit(d->pirq_to_evtchn[irq],
index f6e0eaf59d3d957d9b5d764804c9f17388f53de0..59da03404250ec73ada8b01b6c5e351cf5eeaf4e 100644 (file)
@@ -3095,7 +3095,8 @@ long register_guest_nmi_callback(unsigned long address)
 
     t->vector  = TRAP_nmi;
     t->flags   = 0;
-    t->cs      = !IS_COMPAT(d) ? FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS;
+    t->cs      = (is_pv_32on64_domain(d) ?
+                  FLAT_COMPAT_KERNEL_CS : FLAT_KERNEL_CS);
     t->address = address;
     TI_SET_IF(t, 1);
 
index a693dd7ca4720a5ad386a98198177b8f4987063d..df6954370a48c5208fb63b17f4cf51e645df65c8 100644 (file)
@@ -242,13 +242,15 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( (c.nat = xmalloc(struct vcpu_guest_context)) == NULL )
             goto svc_out;
 
-        if ( !IS_COMPAT(v->domain) )
-            ret = copy_from_guest(c.nat, op->u.vcpucontext.ctxt, 1);
 #ifdef CONFIG_COMPAT
+        if ( !is_pv_32on64_vcpu(v) )
+            ret = copy_from_guest(c.nat, op->u.vcpucontext.ctxt, 1);
         else
             ret = copy_from_guest(c.cmp,
                                   guest_handle_cast(op->u.vcpucontext.ctxt,
                                                     void), 1);
+#else
+        ret = copy_from_guest(c.nat, op->u.vcpucontext.ctxt, 1);
 #endif
         ret = ret ? -EFAULT : 0;
 
@@ -596,12 +598,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( v != current )
             vcpu_unpause(v);
 
-        if ( !IS_COMPAT(v->domain) )
-            ret = copy_to_guest(op->u.vcpucontext.ctxt, c.nat, 1);
 #ifdef CONFIG_COMPAT
+        if ( !is_pv_32on64_vcpu(v) )
+            ret = copy_to_guest(op->u.vcpucontext.ctxt, c.nat, 1);
         else
             ret = copy_to_guest(guest_handle_cast(op->u.vcpucontext.ctxt,
                                                   void), c.cmp, 1);
+#else
+        ret = copy_to_guest(op->u.vcpucontext.ctxt, c.nat, 1);
 #endif
 
         if ( copy_to_guest(u_domctl, op, 1) || ret )
index 09702e3d1f122333a42b60210e683b287437d9d6..3f36d09e831754aaef6331fb14b79f572747e1a7 100644 (file)
@@ -548,7 +548,7 @@ static int evtchn_set_pending(struct vcpu *v, int port)
         return 1;
 
     if ( !test_bit        (port, &shared_info(d, evtchn_mask)) &&
-         !test_and_set_bit(port / BITS_PER_GUEST_LONG(d),
+         !test_and_set_bit(port / BITS_PER_EVTCHN_WORD(d),
                            &vcpu_info(v, evtchn_pending_sel)) )
     {
         vcpu_mark_events_pending(v);
@@ -783,7 +783,7 @@ int evtchn_unmask(unsigned int port)
      */
     if ( test_and_clear_bit(port, &shared_info(d, evtchn_mask)) &&
          test_bit          (port, &shared_info(d, evtchn_pending)) &&
-         !test_and_set_bit (port / BITS_PER_GUEST_LONG(d),
+         !test_and_set_bit (port / BITS_PER_EVTCHN_WORD(d),
                             &vcpu_info(v, evtchn_pending_sel)) )
     {
         vcpu_mark_events_pending(v);
index 8118854eca6edc9a241fea2cb15769a5cbdf5c3c..c481df0f3f87585981f314da4f9ae17c31ac0771 100644 (file)
@@ -225,7 +225,7 @@ static void dump_domains(unsigned char key)
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
                             &shared_info(d, evtchn_mask)),
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
-                            BITS_PER_GUEST_LONG(d),
+                            BITS_PER_EVTCHN_WORD(d),
                             &vcpu_info(v, evtchn_pending_sel)));
             send_guest_vcpu_virq(v, VIRQ_DEBUG);
         }
index 129af3c7da9a4fc3d3040ab33ebe8e7c01058fd4..38113d21df994ce3875e67b6623a869c3f130680 100644 (file)
 #define xen_t_buf t_buf
 CHECK_t_buf;
 #undef xen_t_buf
-#define TB_COMPAT IS_COMPAT(dom0)
 #else
 #define compat_t_rec t_rec
-#define TB_COMPAT 0
 #endif
 
 /* opt_tbuf_size: trace buffer size (in pages) */
index f16ac800ef99906354ffa889157b7734b071d6fd..0a33613caaf2d3902ebbc0bf649ccd22504f903a 100644 (file)
@@ -208,7 +208,7 @@ static int alloc_xenoprof_struct(
     bufsize = sizeof(struct xenoprof_buf);
     i = sizeof(struct event_log);
 #ifdef CONFIG_COMPAT
-    d->xenoprof->is_compat = IS_COMPAT(is_passive ? dom0 : d);
+    d->xenoprof->is_compat = is_pv_32on64_domain(is_passive ? dom0 : d);
     if ( XENOPROF_COMPAT(d->xenoprof) )
     {
         bufsize = sizeof(struct compat_oprof_buf);
index 8fc833a2b9b81608e4fe2de99b19a04e223d4eb8..ec704693088c3ddf0f2f821bc0dfc4b44e6943ac 100644 (file)
@@ -16,7 +16,6 @@
 #define is_pv_32on64_domain(d) (0)
 #endif
 #define is_pv_32on64_vcpu(v)   (is_pv_32on64_domain((v)->domain))
-#define IS_COMPAT(d)           (is_pv_32on64_domain(d))
 
 struct trap_bounce {
     uint32_t      error_code;
index 86395d134e8915fe7941c5afe38be99ae6fcd124..63edd3e6606ba1657cff06def5e409ac73c76faf 100644 (file)
@@ -178,15 +178,10 @@ void xlat_vcpu_runstate_info(struct vcpu_runstate_info *);
 int switch_compat(struct domain *);
 int switch_native(struct domain *);
 
-#define BITS_PER_GUEST_LONG(d) \
-    (!IS_COMPAT(d) ? BITS_PER_LONG : COMPAT_BITS_PER_LONG)
-
 #else
 
 #define compat_handle_is_null(hnd) 0
 
-#define BITS_PER_GUEST_LONG(d) BITS_PER_LONG
-
 #endif
 
 #endif /* __XEN_COMPAT_H__ */
index f859849da650fd9aae1559de72a8041be6d382ec..aa4c7173dfc53ccd88b4fcbca17950b0c814dc5d 100644 (file)
@@ -30,12 +30,11 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t);
 extern struct domain *dom0;
 
 #ifndef CONFIG_COMPAT
-#define MAX_EVTCHNS(d)     NR_EVENT_CHANNELS
+#define BITS_PER_EVTCHN_WORD(d) BITS_PER_LONG
 #else
-#define MAX_EVTCHNS(d)     (!IS_COMPAT(d) ? \
-                            NR_EVENT_CHANNELS : \
-                            sizeof(unsigned int) * sizeof(unsigned int) * 64)
+#define BITS_PER_EVTCHN_WORD(d) (has_32bit_shinfo(d) ? 32 : BITS_PER_LONG)
 #endif
+#define MAX_EVTCHNS(d) (BITS_PER_EVTCHN_WORD(d) * BITS_PER_EVTCHN_WORD(d) * 64)
 #define EVTCHNS_PER_BUCKET 128
 #define NR_EVTCHN_BUCKETS  (NR_EVENT_CHANNELS / EVTCHNS_PER_BUCKET)
 
@@ -542,10 +541,6 @@ uint64_t get_cpu_idle_time(unsigned int cpu);
 #define IS_PRIV(_d) ((_d)->is_privileged)
 #define IS_PRIV_FOR(_d, _t) (IS_PRIV(_d) || ((_d)->target && (_d)->target == (_t)))
 
-#ifndef IS_COMPAT
-#define IS_COMPAT(d) 0
-#endif
-
 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
 
 #define is_hvm_domain(d) ((d)->is_hvm)